package com.one.square.gateway.service;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.one.square.core.constant.GlobalConstants;
import com.one.square.core.constant.SecurityConstants;
import com.one.square.core.entity.SysMenu;
import com.one.square.gateway.swagger.SwaggerAggProperties;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AnonymousAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.oauth2.jwt.Jwt;
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken;
import org.springframework.util.AntPathMatcher;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author cwm
 * @Description 请求权限判断service
 * @date 2021/10/27 上午10:48
 * @Version 1.0
 */
@Slf4j
public abstract class DefaultPermissionServiceImpl {
    private final AntPathMatcher antPathMatcher = new AntPathMatcher();

    public abstract List<SysMenu> findMenuByRoleCodes(List<String> roleCodes);

    public boolean hasPermission(Authentication authentication, String requestMethod, String requestURI) {
        // 前端跨域OPTIONS请求预检放行 也可通过前端配置代理实现
        if (HttpMethod.OPTIONS.name().equalsIgnoreCase(requestMethod)) {
            return true;
        }
        if (!(authentication instanceof AnonymousAuthenticationToken)) {
            //超级管理员admin不需认证
            boolean b = authentication.getAuthorities().stream()
                    .map(GrantedAuthority::getAuthority)
                    .anyMatch(
                            authority -> {
                                String roleCode = authority.substring(SecurityConstants.AUTHORITY_PREFIX.length());
                                return GlobalConstants.ROOT_ROLE_CODE.equals(roleCode);
                            }
                    );
           if (!b){
               JwtAuthenticationToken jwtAuthenticationToken= (JwtAuthenticationToken)authentication;
               Map<String, Object> tokenAttributes = jwtAuthenticationToken.getTokenAttributes();
               if (CollectionUtil.isNotEmpty(tokenAttributes)){
                   Object o = tokenAttributes.get(SecurityConstants.GRANT_TYPE_KEY);
                   if (Objects.nonNull(o)){
                       if (GlobalConstants.CLIENT_CREDENTIAL.equals(o)){
                           //判断是否是client模式 如果是clilent 模式直接放行  todo  后期加入对client权限控制
                           return true;
                       }
                   }
               }
               List<SimpleGrantedAuthority> grantedAuthorityList = (List<SimpleGrantedAuthority>) authentication.getAuthorities();
               if (CollectionUtil.isEmpty(grantedAuthorityList)) {
                   log.warn("角色列表为空：{}", authentication.getPrincipal());
                   return false;
               }
               List<String> roleCodes = grantedAuthorityList.stream().map(item -> item.getAuthority().substring(SecurityConstants.AUTHORITY_PREFIX.length()))
                       .collect(Collectors.toList());
               List<SysMenu> menuList = findMenuByRoleCodes(roleCodes);
               for (SysMenu menu : menuList) {
                   if (StrUtil.isNotEmpty(menu.getUrl()) && antPathMatcher.match(menu.getUrl(), requestURI)) {
                       if (StrUtil.isNotEmpty(menu.getPathMethod())) {
                           return requestMethod.equalsIgnoreCase(menu.getPathMethod());
                       } else {
                           return true;
                       }
                   }
               }
           }else {
               return true;
           }
        }
        return false;
    }
}
